import Shape2D from "./Shape2D";
import Point3D from "../Point/Point3D";
import Angle3D from "../Movement/Angle3D";
import Point2D from "../Point/Point2D";
import eUtils from '../../utils/every-utils';

export default class Shape3D extends Shape2D {

    /**
     * @param centre {Point3D}
     * @param angle {Angle3D}
     */
    constructor(centre = new Point3D(0, 0, 0), angle = new Angle3D()) {
        super(centre, angle);
    }

    /**
     * @param shape {Shape3D}
     */
    getDistanceFrom(shape) {
        return super.getDistanceFrom(shape);
    }

    nextSurfaceData() {
        return this.surfaces && this.surfaces.pop();
    }

    hasNextSurface() {
        return this.surfaces && this.surfaces.length > 0;
    }

    startDataInit() {
        this.beforeDataInit();
        this.drawnDataInit();
        this.afterDataInit();
    }

    drawnDataInit() {
    }

    beforeDataInit() {
        this.surfaces = [];
    }

    afterDataInit() {
        this.sortZIndex();
    }

    sortZIndex() {
        this.surfaces.sort((a, b) => {
            let aZs = eUtils['parseArrayByProperty'](a.points, 'z');
            let bZs = eUtils['parseArrayByProperty'](b.points, 'z');
            let aSum = eUtils['getSumInArray'](aZs);
            let bSum = eUtils['getSumInArray'](bZs);
            return bSum - aSum;
        })
    }


    /**
     * @param deg3D {Angle3D}
     * @param point {Point3D=}
     */
    rotate(deg3D, point) {
        this.rotateX(deg3D.x);
        this.rotateY(deg3D.y);
        this.rotateZ(deg3D.z);
    }

    rotateX(deg) {
        this.angle.x += deg;
        this.angle.x %= 360;
    }

    rotateY(deg) {
        this.angle.y += deg;
        this.angle.y %= 360;
    }

    rotateZ(deg) {
        this.angle.z += deg;
        this.angle.z %= 360;
    }

    applyDeg(point) {
        this.applyX(point);
        this.applyY(point);
        this.applyZ(point);
    }

    applyX(point) {
        let centre = new Point2D(this.centre.y, this.centre.z);
        let yzPoint = new Point2D(point.y, point.z);
        let distance = centre['getDistanceFromAnotherPoint'](yzPoint);
        let angle = centre['getDegFromAnotherPoint'](yzPoint);
        let resultPoint2D = centre['getOtherPointFromDistanceAndDeg'](distance, angle + this.angle.x);
        point.y = resultPoint2D.x;
        point.z = resultPoint2D.y;
    }

    applyY(point) {
        let centre = new Point2D(this.centre.x, this.centre.z);
        let xzPoint = new Point2D(point.x, point.z);
        let distance = centre['getDistanceFromAnotherPoint'](xzPoint);
        let angle = centre['getDegFromAnotherPoint'](xzPoint);
        let resultPoint2D = centre['getOtherPointFromDistanceAndDeg'](distance, angle + this.angle.y);
        point.x = resultPoint2D.x;
        point.z = resultPoint2D.y;
    }

    applyZ(point) {
        let centre = new Point2D(this.centre.x, this.centre.y);
        let xyPoint = new Point2D(point.x, point.y);
        let distance = centre['getDistanceFromAnotherPoint'](xyPoint);
        let angle = centre['getDegFromAnotherPoint'](xyPoint);
        let resultPoint2D = centre['getOtherPointFromDistanceAndDeg'](distance, angle + this.angle.z);
        point.x = resultPoint2D.x;
        point.y = resultPoint2D.y;
    }

}